package org.jivesoftware.spark.crowd.packet;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromMatchesFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.spark.crowd.CrowdsManager;
import org.jivesoftware.spark.crowd.Param;
import org.jivesoftware.spark.crowd.impl.Crowd;
import org.jivesoftware.spark.crowd.impl.Member;
import org.jivesoftware.spark.crowd.packet.DiscoverCrowds.CrowdItem;
/**
 * 
 * @author liyuan
 *
 */
public class CrowdsIQManager implements PacketListener{
	/**
	 * singleton mode ,support only one service name.
	 */
	private static CrowdsIQManager instance;
	/**
	 * 
	 */
	private Connection conn;
	/**
	 * 
	 */
	private CrowdsManager crowdsManager;
	/**
	 * the crowd service name
	 */
	private String crowdServiceName;
	
	
	
	private ReceivedPacketProcesser packetProcesser;
	public static CrowdsIQManager getInstance(Connection conn,String serviceName){
		if(instance == null)
			instance = new CrowdsIQManager(conn,serviceName);
		return instance;
	}
	private CrowdsIQManager(Connection conn,String serviceName){
		this.conn = conn;
		this.crowdsManager = CrowdsManager.getInstance();
		this.crowdServiceName = serviceName;
		this.packetProcesser = ReceivedPacketProcesser.getInstance();
		init();
	}
	private void init(){
		DiscoverCrowds.DiscoverCrowdsProvider.getInstance();
		DiscoverMembers.DiscoverMembersProvider.getInstance();
		
//		 PacketFilter fromFilter = new FromMatchesFilter(crowdServiceName + "." + conn.getServiceName());
		 PacketFilter fromFilter = new FromMatchesFilter(conn.getServiceName());
		  PacketFilter typeFilter = new PacketTypeFilter(IQ.class);
	        PacketFilter andFilter = new AndFilter(typeFilter, fromFilter);
		
	     conn.addPacketListener(this, typeFilter );
	}
	public void loadLocalCrowds()throws Exception{	
		
		IQ fetchLocalCrowds = new IQ(){
			@Override
			public String getChildElementXML() {			
				return "<"+crowdServiceName+" xmlns=\"" + Param.discoLocalCrowds_NS + "\"/>";
			}			
		};
//		fetchLocalCrowds.setTo(Param.getFullCrowdDomain());
		fetchLocalCrowds.setTo(conn.getServiceName());
//		fetchLocalCrowds.setFrom(Param.getFullJID());
		fetchLocalCrowds.setType(IQ.Type.GET);
		
		
		
		conn.sendPacket(fetchLocalCrowds);

	}
	
	public void loadMembers(final String crowdName)throws Exception{
		IQ fetchCrowdMembers = new IQ(){
			@Override
			public String getChildElementXML() {
				
				return "<"+crowdServiceName+" xmlns=\"" + Param.discoCrowdMembers_NS + "\" crowdname=\"" + crowdName + "\"/>";
			}			
		};
		fetchCrowdMembers.setTo(conn.getServiceName());
		fetchCrowdMembers.setFrom(Param.getBareAddress());
		fetchCrowdMembers.setType(IQ.Type.GET);

		conn.sendPacket(fetchCrowdMembers);
		
	}
	@Override
	public void processPacket(Packet packet) {
		
		if(packet instanceof DiscoverCrowds){
			ArrayList<Crowd> crowds = new ArrayList<Crowd>();
			
			DiscoverCrowds dcs = (DiscoverCrowds)packet;
			Iterator<CrowdItem> items = dcs.getItems();
			while(items.hasNext()){
				CrowdItem item = (CrowdItem)items.next();
				String name = item.getName();
				String creatorJID = item.getCreatorJID();
				String creatorNickName = item.getCreatorNickName();
				String createTime = item.getCreateTime();
				String title = item.getTitle();
				String crowdJID = item.getCrowdJID();
				
				
				Crowd crowd = new Crowd(name,new Member(creatorJID,creatorNickName),crowdJID,createTime,title);
				
				crowds.add(crowd);
			}
			
			if(dcs.getXmlns().equals(Param.discoLocalCrowds_NS))
				packetProcesser.receiveCrowdsLocal(crowds);
			
			
		}else if(packet instanceof DiscoverMembers){
			List<Member> members = new ArrayList<Member>();
			
			
			DiscoverMembers dms = (DiscoverMembers)packet;
			String crowdName = dms.getCrowdName();
			Iterator<DiscoverMembers.MemberItem> items = dms.getMembers();
			while(items.hasNext()){
				DiscoverMembers.MemberItem item = (DiscoverMembers.MemberItem)items.next();
				String bareJID = item.getJID();
				String nickname = item.getName();
				
				Member member = new Member(bareJID,nickname);
				member.setPresence(new Presence(Presence.Type.unavailable));
				members.add(member);
			}
			if(members.size() > 0){
				
				packetProcesser.receiveMembersInACrowd(crowdName,members);
			}
			//TODO 1.add members to the crowdImpl's members list.
			//TODO 2.show them on the MemberListPane,and add listeners.
		}
			
		
	}
	public static CrowdsIQManager getInstance() {
		return instance;
	}
	
	public void send(IQ packet){
		conn.sendPacket(packet);
	}
	public IQ sendAndWait(IQ packet)throws XMPPException{
		PacketFilter filter = new PacketIDFilter(packet.getPacketID());
		PacketCollector collector = conn.createPacketCollector(filter);
		
		conn.sendPacket(packet);
		
		IQ result = (IQ)collector.nextResult(5000);
		collector.cancel();
		if (result == null) {
            throw new XMPPException("服务器没有回应");
        }
        else if (result.getError() != null) {
        	if(result instanceof DiscoverCrowds){
        		String ds = ((DiscoverCrowds)result).getXmlns();
        		System.out.println(ds);
        	}
        	
            throw new XMPPException(result.getError());
        }		
		return result;
	}
	
}
